package spring.fox.context;

import fox.framework.rpc.context.ConfigurableRegisteredRpcObjectFactory;
import fox.framework.rpc.context.definition.RpcDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author cuichao
 * @Description: SpringFoxRpcObjectFactory
 * @Date: create in 2021/3/9 23:23
 */
public class SpringFoxRpcObjectFactory extends ConfigurableRegisteredRpcObjectFactory {


    public static final String RPC_DEFINITION_KEY = "RPC_DEFINITION_REF";

    private ConfigurableListableBeanFactory beanFactory;

    private ConcurrentMap<String, RpcDefinition> definitionObjects = new ConcurrentHashMap<>(256);

    public SpringFoxRpcObjectFactory(ConfigurableListableBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public void register(String name, RpcDefinition definition, Object object) {

    }

    @Override
    public void register(String name, RpcDefinition definition) {

    }

    @Override
    public boolean contain(String name) {
        return beanFactory.containsBean(name);
    }

    @Override
    public RpcDefinition getDefinition(String name) {
        return definitionObjects.getOrDefault(name,null);
    }

    @Override
    public Collection<RpcDefinition> getAllDefinitions() {
        return Collections.unmodifiableCollection(definitionObjects.values());
    }

    @Override
    public Object getObject(String name) {
        return beanFactory.getBean(name);
    }

    @Override
    public <T> T getObject(Class<T> cls) {
        return beanFactory.getBean(cls);
    }

    @Override
    protected void doRefresh() {
        String[] names = beanFactory.getBeanDefinitionNames();

        for (String name : names) {
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
            //BeanDefinition 是否有RpcDefinition
            if (!beanDefinition.hasAttribute(RPC_DEFINITION_KEY)) {
                continue;
            }
            Object attribute = beanDefinition.getAttribute(RPC_DEFINITION_KEY);
            if (!(attribute instanceof RpcDefinition)) {
                throw new IllegalArgumentException(attribute.getClass().getName()+"is not cast be "+RpcDefinition.class);
            }

            RpcDefinition definition = (RpcDefinition) attribute;
            System.err.println("beanName: " + name +
                            "   metaspace: "+definition.metaspace()+
                            "   isProvider" + definition.isProvider()
            );
            definitionObjects.putIfAbsent(definition.metaspace(),definition);
        }
    }





}
